-- 2022-8-6

--[[ 13.0
    建议在阅读本章之前 了解逻辑运算 移位运算 算术运算

    Lua语言处理二进制数据的方式与处理文本的方式类似
    Lua语言中的字符串可以包含任意字节，并且几乎所有能够处理字符串的库函数也能处理任意字节
    我们甚至可以对二进制数据进行模式匹配
    以此为基础，Lua5.3中引入了用于操作二进制数据的额外机制
    除了整型数外，该版本还引入了位操作及用于打包/解包二进制数据的函数
    
    本章，我们会学习上述内容，以及Lua语言用于处理二进制数据的其他工具
]]

---[[ 13.1 位运算
    -- Lua语言从5.3版本开始提供了针对数值类型的一组标准位运算符
    -- 与算术运算符不同的是，位运算符只能用于整型数
    -- 位运算符包括&(按位与),|(按位或),~(按位异或),>>(逻辑右移),<<(逻辑左移)和一元运算符~(按位取反)
    -- (请注意，在其他一些语言中，异或运算符为^,而在Lua语言中^代表幂运算)
    print(string.format("%x",0xff))        -- ff    (48个0)0000 0000 1111 1111
    print(string.format("%x",0xabcd))      -- abcd  (48个0)1010 1011 1100 1101
    print(string.format("%x",0xff&0xabcd)) -- cd    (48个0)0000 0000 1100 1101
    print(string.format("%x",0xff|0xabcd)) -- abff  (48个0)1010 1011 1111 1111
    print(string.format("%x",0xff~0xabcd)) -- ab32  (48个0)1010 1011 0011 0010
    print(string.format("%x",-1))          -- ffffffffffffffff       (48个1)1111 1111 1111 1111
    print(string.format("%x",0xaaaa))      -- aaaa                   (48个0)1010 1010 1010 1010
    print(string.format("%x",0xaaaa ~ -1)) -- ffffffffffff5555(64位) (48个1)0101 0101 0101 0101 
    print(string.format("%x",0))           -- 0                             0000 0000 0000 0000
    print(string.format("%x",~0))          -- ffffffffffffffff              1111 1111 1111 1111 
    -- (本章几个例子会使用函数string.format来输出十六进制的结果)

    -- 所有的位运算都针对构成一个整型数的所有位
    -- 在标准Lua中，也就是64位，这对于使用32位整型数的算法可能会成为问题 因为转换为位模式的时候会出现错位 因为需要显示所有的数字 不会省略0
    -- 不过，要操作32位整型数也不难，除了右移操作外，只要忽略搞32位，那么所有针对64位整型数的操作与针对32位整型数的操作都一样
    -- 这对于加减乘法都一样，因此只需要在操作32位整型时，只需要抹去高32位就可以了

    -- 两个移位操作都会用0填充空出的位，这种通常被称为逻辑移位
    -- Lua没有提供算术右移。即使用符号位填充空出的位
    -- 但是我们可以通过向下取整除法(floor除法),除以合适的2的整数次幂来实现算术右移(例如,x//16与算术右移4位等价)

    -- 移位数是负数表示反方向的移位,即a>>n与a<<-n等价
    print(string.format("%x",0xff<<12)) -- ff000 (16进制一位代表2进制四位)
    print(string.format("%x",0xff>>-12)) -- ff000

    -- 如果移位数等于或大于整型表示的位数(标准Lua为64位,精简Lua为32位),由于所有的位都被从结果中移除了,所以结果为0
    print(string.format("%x",-1<<80)) -- 0
--]]